<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>JavaScript面向对象</title>
</head>
<body>
  <script>
    var obj = new Function('a', 'b', 'return a+b')  
    var s = obj(2, 5)
    console.log(s)

    var obj = {name: 'zhangsan', age: 21}
    console.log(obj instanceof Object)

    // 
    var box = new Object()
    box.name= 'lisi'
    box.age = 23
    box.infos = function(str){
      return this.name + this.age + str
    }
    console.log(box.infos('吃饭'))


    function Person(name, age){
      this.name = name
      this.age = age
      // this代表当前对象 
      this.say = function(){
        console.log(this.name)
      }
    }

    var person = new Person('wangwu', 24)
    person.say()

    function createObject(name,age){
      var obj = new Object()
      obj.name = name
      obj.age = age
      person.say = function(){
        console.log(this.name + '-----' + this.age)
      }
      return obj
    }
    
    createObject('l', 23)
    person.say()







    console.log('-------------')
    function Test(){}
    console.log(Test.prototype)
    Test.prototype.color = 'red'
    Test.prototype.height = '1.7'
    Test.prototype.showInfo = function(){
      console.log(this.color + '+++++' + this.height)
    }
    var test = new Test()
    test.showInfo()

    // 混合模式
    function blog(name, url, friend){
      this.name = name
      this.url = url
      this.friend = friend
    }
    blog.prototype = {
      test: 'awd',
      showInfo: function(){
        console.log(this.name + '-----' + this.url)
      }
    }
    var peo = new blog('张三','http://www.baidu.com', 'jack')
    peo.showInfo()
    // 遍历对象的属性 可以当做数组处理 for in
    var ren = {}
    ren.name = 'zhangsan'
    ren.age = 19
    ren.len = '180'
    ren.demo = function(){
      console.log(this.len)
    }
    for(var i in ren){
      console.log(ren[i])
    }
    function stu() {
      this.name = '李四'
      this.age = 20
      this.leng = '175'
      this.demo = function(){
        console.log(this.leng)
      }
    }

    var s = new stu()
    for(var key in s){
      console.log(key)
    }


    // 面向对象的封装
    function demo(){
      var n = 1;
      function test(){ // 特权方法 外部调用的出口
        return ++n
      }
      /**
       * this.test = function(){
       *    return ++n
       * }
       *  
       */
      return test
    }
    console.log(demo()())


    function A(){
      function _xx(){console.log(111)}
      this.xx = function(){
        return _xx
      }
    }

    A.prototype = {
      oth: function(){
        console.log('普通方法')
      }
    }

    var a = new A()
    var b = a.xx()
    b()

    console.log('---------原型和原型链---------')
    var person = function(){
      this.name = 'zhangsan'
    }
    person.prototype.say = function(){
      console.log('天气挺好')
    }
    person.prototype.gongzi = 500

    var programmer = function(){}
    programmer.prototype = new person()
    programmer.prototype.wcd = function(){
      console.log('明天天气也不错')
    }
    var p = new programmer()

    p.say() // p只是个变量，没有say方法 会去__proto__中去找，就是person.prototype中找 
    console.log(p.__proto__ === person.prototype)
    p.wcd()
  
    // p.say(); p.__proto__ --> programmer.prototype == p1 --> p1.__proto__ == person.prototype.say()
    // 原型链实现过程
    
    console.log('--------原型链继承----------')
    function per(name, age){
      this.name = name;
      this.age = age
    }
    per.prototype.sayName = function(){
      console.log("属性name值" + this.name)
    }
    var ps = new per('lucky', 20)
    ps.sayName()
    function student(){}
    student.prototype = new per('李斯', 18)
    student.prototype.grade = 3
    student.prototype.test = function(){
      console.log(this.grade)
    }
    var s = new student()
    s.test()
    s.sayName()

    console.log('----------------封装-------------------')

    function demo2(){
      var n = 1 // 局部变量在函数外部无法访问
      function test(){ // 外部调用的出口
        n++
      }
      test()
      return n
    }

    function demo3(){
      var n = 1
      return function(){ // 函数内部变量无法访问，采用中转站，特权方法访问变量
        return ++n
      }
      // this.add = function(){  // 特权方法，可以访问局部变量
      //   return ++n
      // }
      
    }
    var at = demo3()
    console.log(at())


    function A(){
      var t = 3
      function _xx(){console.log(++t)}
      this.xx = function(){
        return _xx
      }
      function _del(){console.log(--t)}
      this.jj = function(){
        return _del
      }
    }
    A.prototype.oth = function(){
      console.log('普通方法')
    }
    var _a = new A()
    var _b = _a.xx()
    var _j = _a.jj()
    _b()
    _b()
    _j()

    console.log('--------------原型继承---------------')
    var animate = function(){
      this.name = 'panda'
    }
    animate.prototype.say = function(){
      console.log('天气挺好')
    }
    animate.prototype.gz = 500

    var panda = function(){}
    var ani = new animate()
    panda.prototype = ani
    panda.prototype.wcd = function(){
      console.log('panda天气挺不错')
    }
    panda.prototype.gz = 1000


    var pan = new panda()
    pan.say()
    pan.wcd()
    console.log(pan.gz)

    /**
    1. var p = {} 创建对象
    2. p.__proto__ = person.prototype __proto__ 自带一个属性
    3. 创建对象（初始化对象）p --> person.call(p)
    */
    console.log(ani.__proto__ == animate.prototype)
    // p.name 不存在 __proto__去查找p.__proto__对象 不存在 p.__proto__.__proto__
  </script>
</body>
</html>